

#include "trans-p.h"
#include "utils.h"
#include "sc-p.h"
#include "measure.h"
#ifdef MEDIA_CH4IR
#include "../sc-p_ch4ir/uart.h"
#endif
			

u8 add_params_num = 0;					// set_add_data

#ifdef MEDIA_CO2
u16 debu_act = 0; 
u16 debu_ref = 0;
#endif


u8 timeout = 0;
u8 t0_cnt = 0;

void set_add_data()
{
#ifdef MEDIA_PS 
static i8 param_send = 0;

	if (param_send == 0)
	{
		t_pom = v_pres;
		t_pom |= (1 << 14);
	}
	if (param_send == 1)
	{
		t_pom = v_rh;
		t_pom |= (2 << 14);
	}
	if (param_send == 2)
	{
		t_pom = v_temp;
		t_pom |= (3 << 14);
		param_send = 0;
	}
	else
		param_send++;
#elif MEDIA_PD
	t_pom = v_pres;
	t_pom |= (1 << 14);
	
#endif

	static u16 old_charge = 0;
	
	if (t_addr != 0)
		return;
	
	float charge = (float)(v_pow - v_aku) / 0.0056;
	if ((charge < 4000) && (old_charge > 4000))			// less than 4mA
	{
		add_params_num = 1;
	}
	old_charge = charge;
	
	switch (add_params_num)
	{
		case 0:
			t_addr = ADDR_VAKU;
			t_data = v_aku;
		break;
		case 1:
			t_addr = ADDR_VPOW;
			t_data = v_pow;
		break;
		case 2:
			t_addr = ADDR_VDC;
			t_data = v_dc;
		break;
		case 3:
			t_addr = ADDR_TEMP;
			t_data = v_temp;
			break;
	}
	add_params_num++;
	if (add_params_num > 3)
		add_params_num = 0;
}

inline void w_p_clk_l()
{
	while(PCK && !timeout);
}

inline void w_p_clk_h()
{
	while(!PCK && !timeout);
}


u8 get_8b_p()
{
	static u8 byte = 0;
	static u8 val  = 0;
	static i8 c = 0;
	
	byte = 0;
	c = 7;
	
	for (; c >= 0; c--)
	{
		w_p_clk_l();	// wait for falling edge
		PTX_H;
#ifndef MEDIA_CH4IR
		val = ( PIND & (1 << PIND0 )); // read bit
#else
		val = ( PIND & (1 << PIND5 )); // read bit

#endif
		if (val)
			byte |= ( 1 << c );
		PTX_L;
		w_p_clk_h();	// wait for high clk again
		
	}

	return byte;
}

void set_8b_p(u8 data)
{
	static i8 c;
	c = 7;
	for (; c >= 0; c--)
	{
		w_p_clk_l();		// wait for low level
		
		if (data & (1 << c) )
		{
			PTX_H;
		}
		else
		{
			PTX_L;			// setup data
			
		}
		w_p_clk_h();		// wait for clk to became high again
	}

}



void add_crc8(u8 byte)
{
	crc_data[crc_data_len] = byte;
	crc_data_len++;
}

void add_crc16(u16 word)
{
	crc_data[crc_data_len] = (word & 0xFF00) >> 8;
	crc_data_len ++;
	crc_data[crc_data_len] = (word & 0xFF) ;
	crc_data_len ++;
}

extern float xxc;
void trans()
{

	TR_P_DISABLE;
	set_add_data();
	t0_cnt = 0; 
	timeout = 0;
	T0START; 
	

	
	crc_data_len = 0;
	add_crc8(t_addr);
	add_crc16(t_data);
	add_crc16(t_pom);
	t_crc = crc8(crc_data,crc_data_len);
	
	PTX_L;
	for (u8 c = 0; c < 200; c++)
	{
		if (PCK)		// wait for clock to became high again
		{
			break;
		}		
		WAITUS(10);	// max 2ms
		
		if (c > 190)
		{
			PTX_H;
			TR_P_ENABLE;
			T0STOP;
			return;		/// no response, quit transmision
		}
		
	}
	
	r_addr = get_8b_p();
	r_data = (get_8b_p() << 8);
	r_data |= get_8b_p();
	r_crc = get_8b_p();

	
	set_8b_p(t_addr);
	set_8b_p((t_data & 0xFF00 )>> 8);
	set_8b_p( t_data & 0xFF );
	set_8b_p((t_pom & 0xFF00 )>> 8);
	set_8b_p( t_pom & 0xFF );
	set_8b_p(t_crc);
	
	crc_data_len = 0;
	add_crc8(r_addr);
	add_crc16(r_data);
	u8 xcrc = crc8(crc_data,crc_data_len);


	w_p_clk_l();
	if (xcrc == r_crc)
	{
		PTX_L;
		tr_ok = 1;
	}
	else
	{
		tr_ok = 0;
		PTX_H;
	}
	w_p_clk_h();
	WAITUS(150);

	PTX_H;
	TR_P_ENABLE;

	

	
	if (tr_ok)
	{
		t_addr = 0;
		t_data = 0;
		interpret();
	}

}


	
	
#if defined(MEDIA_CH4) || defined(MEDIA_CH4IR)
	
void interpret()
{
	switch(r_addr)
	{
		case P_ADDR_DCOFF:
		{
			DCDC_OFF;
			break;
		}	
		
		case P_ADDR_INCAKU:
		{
			x_aku = read_word(EEP_X_AKU);
			x_aku += ADD_LESS;
			write_word(EEP_X_AKU,x_aku);
			add_params_num = 0;
			break;
		}
		case P_ADDR_DECAKU:
		{
			x_aku = read_word(EEP_X_AKU);
			x_aku -= ADD_LESS;
			write_word(EEP_X_AKU,x_aku);
			add_params_num = 0;
			break;
		}
		case P_ADDR_INCPOW:
		{
			x_pow = read_word(EEP_X_POW);
			x_pow += ADD_LESS;
			write_word(EEP_X_POW,x_pow);
			add_params_num = 1;
			break;
		}
		case P_ADDR_DECPOW:
		{
			x_pow = read_word(EEP_X_POW);
			x_pow -= ADD_LESS;
			write_word(EEP_X_POW,x_pow);
			add_params_num = 1;
			break;
		}
		case P_ADDR_INCAKUM:
		{
			x_aku = read_word(EEP_X_AKU);
			x_aku += ADD_MORE;
			write_word(EEP_X_AKU,x_aku);
			add_params_num = 0;
			break;
		}
		case P_ADDR_DECAKUM:
		{
			x_aku = read_word(EEP_X_AKU);
			x_aku -= ADD_MORE;
			write_word(EEP_X_AKU,x_aku);
			add_params_num = 0;
			break;
		}
		case P_ADDR_INCPOWM:
		{
			x_pow = read_word(EEP_X_POW);
			x_pow += ADD_MORE;
			write_word(EEP_X_POW,x_pow);
			add_params_num = 1;
			break;
		}
		case P_ADDR_DECPOWM:
		{
			x_pow = read_word(EEP_X_POW);
			x_pow -= ADD_MORE;
			write_word(EEP_X_POW,x_pow);
			add_params_num = 1;
			break;
		}
		
		case P_ADDR_L_FACTORY:
		{
				snxa = 1.70766882;
				snxb = 1349;
		
				nxa = 1.70766882;
				nxb = 1349;

				x_scn = 1900;
				x_szn = 800;

				x_cn = 1900;
				x_zn = 800;
		
 				stn = 198;

				write_double(EEP_SNXA,snxa);
				write_double(EEP_SNXB,snxb);
				write_double(EEP_NXA,nxa);
				write_double(EEP_NXB,nxb);
		
				write_word(EEP_X_SZN,x_szn);
				write_word(EEP_X_SCN,x_scn);
		
				write_word(EEP_X_ZN,x_zn);
				write_word(EEP_X_CN,x_cn);

 				write_word(EEP_STN,stn);
				 

			
			break;
		}
		
		case P_ADDR_IR_INIT:
		{
			#ifdef MEDIA_CH4IR
			spec_aquire = CALIB_FACT;
			#endif
			break;
		}
		
		case P_ADDR_H_FACTORY:
		{
			swxa = 0.003907;
			swxb = 14.15;
			swxc = 17990;
		
			wxa = 0.003307;
			wxb = 14.15;
			wxc = 17990;
					
			x_scw = 2195;
			x_szw = 992;
			
			x_cw = 2195;
			x_zw = 992;

			//stw1 = 300;
			//stw2 = 952;

			write_double(EEP_SWXA,swxa);
			write_double(EEP_SWXB,snxb);
			write_double(EEP_SWXC,swxc);
			write_double(EEP_WXA,wxa);
			write_double(EEP_WXB,wxb);
			write_double(EEP_WXC,wxc);

			write_word(EEP_X_SZW,x_szw);
			write_word(EEP_X_SCW,x_scw);
					
			write_word(EEP_X_ZW,x_zw);
			write_word(EEP_X_CW,x_cw);
					
// 			write_word(EEP_STW1,stw1);
// 			write_word(EEP_STW2,stw2);
			#ifdef MEDIA_CH4IR
			aquire = CALIB_FACT;
			#endif
			
			break;
		}
		
		case P_ADDR_SW_HRANGE:
		{
			auto_range = 0;
			SEL_HR;
			wait_range = SWITCH_TIME;
			range = 1;
			break;
		}
		
		case P_ADDR_SW_HRANGEUSER:
		{
			#ifdef MEDIA_CH4IR
			
			break;
			#endif
			
			auto_range = 1;
			SEL_HR;
			wait_range = SWITCH_TIME;
			range = 1;
			break;
		}
		
		case P_ADDR_SW_LRANGE:
		{
			auto_range = 1;
			if (t_pom & 0x8000)
			{
				if (!(t_pom & 0x2000))	// ~minus
				{
					if ((t_pom & 0x0FFF) > 40)	// turn only auto_range, meas > 4.0%
						break;
				}
			}
			SEL_LR;
			wait_range = SWITCH_TIME;
			range = 0;
			break;
		}
		
		case P_ADDR_L_RESET:
		{
			ser_def_low();
			break;
		}
		
		case P_ADDR_H_RESET:
		{
			ser_def_high();
			break;
		}
		
		case P_ADDR_SCALLZ:
		{
			cal_l_zero();
			#ifdef MEDIA_CH4IR
			spec_aquire = CALIB_ZERO;
			#endif
			
			break;
		}
		case P_ADDR_SCALLS:
		{
			#ifdef MEDIA_CH4IR
			sens_value = r_data;
			spec_aquire = CALIB_SENSE;
			break;
			#endif
			cal_l_sens(r_data);
			
			snxa = nxa;
			snxb = nxb;
			write_word(EEP_SNXA,snxa);
			write_word(EEP_SNXB,snxb);
			
			x_szn = x_zn;
			x_scn = x_cn;
			write_word(EEP_X_SZN,x_szn);
			write_word(EEP_X_SCN,x_scn);
			
			
			break;
		}

		
		case P_ADDR_CALLZ:
		{
			#ifdef MEDIA_CH4IR
			spec_aquire = CALIB_ZERO;
			#endif
			cal_l_zero();
			
			
			break;
		}
		case P_ADDR_CALLS:
		{
			#ifdef MEDIA_CH4IR
			
			sens_value = r_data;
			spec_aquire = CALIB_SENSE;
			break;
			#else
			cal_l_sens(r_data);
			#endif

			break;
		}
		
		case P_ADDR_SCALHZ:
		{
			#ifdef MEDIA_CH4IR
			spec_aquire = CALIB_FACT;
			#else
			s_cal_h_zero();
			#endif
			break;
		}
		case P_ADDR_SCALHS1:
		{	
			s_cal_h_sens1(r_data);
			
			break;
		}
		case P_ADDR_SCALHS2:
		{
			s_cal_h_sens2(r_data);
			break;
		}
		
		case P_ADDR_CALHZ:
		{
			#ifdef MEDIA_CH4IR
			spec_aquire = CALIB_ZERO;
			#else
			cal_h_zero();
			#endif
			
			break;
		}
		case P_ADDR_CALHS:
		{
#ifdef MEDIA_CH4IR
			sens_value = r_data ;
			spec_aquire = CALIB_SENSE;

			break;
#endif
			cal_h_sens(r_data);
			auto_range = 1;

			
			break;
		}
		
		case P_ADDR_RESET_DEFAULTS:
		{
			nxa = read_double(EEP_NXA);
			nxb = read_double(EEP_NXB);
			
			wxa = read_double(EEP_WXA);
			wxb = read_double(EEP_WXB);
			wxc = read_double(EEP_WXC);
			
			x_zn = read_word(EEP_X_ZN);
			x_cn = read_word(EEP_X_CN);
			
			x_zw = read_word(EEP_X_ZW);
			x_cw = read_word(EEP_X_CW);
			
			auto_range = 1;
			break;
		}
	}		

}

#endif

